package top.hmtools.services.adapter;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.sql.DataSource;

import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;

import com.alibaba.druid.pool.DruidDataSourceFactory;

import top.hmtools.beans.DBConnectInfoBean;
import top.hmtools.beans.columnsInfoBeans.ColumnsBaseInfoBean;
import top.hmtools.beans.tableInfoBeans.TableBaseInfoBean;
import top.hmtools.commons.AlertUtil;
import top.hmtools.enums.EDBType;

/**
 * 数据库链接转换基础类
 * <br>链接用于进行反向生成操作的数据库
 * @author HyboJ
 *
 */
public abstract class BaseDBAdapter  {
	
	protected Logger logger = LoggerFactory.getLogger(this.getClass());

	protected SqlSession getSqlSession(DBConnectInfoBean bean){
		SqlSession result = null;
		//测试数据库链接
		Connection connection = null;
		boolean isConnectionOK = false;
		try {
			String driverClassName = EDBType.getDriverClassNameByTypeCode(bean.getDb_type());
			Class.forName(driverClassName);
		    connection = DriverManager.getConnection(bean.getUrl(),bean.getUsername(),bean.getPassword());
		    PreparedStatement prepareStatement = connection.prepareStatement("SELECT 'x';");
		    ResultSet resultSet = prepareStatement.executeQuery();
		    isConnectionOK = resultSet.next();
		} catch (Exception e) {
			e.printStackTrace();
			logger.error("测试数据链接失败："+e.getMessage(),e);
			AlertUtil.showErrorAlert("测试数据链接失败："+e.getMessage());
		}finally{
			if(connection != null){
				try {
					connection.close();
				} catch (SQLException e) {
					e.printStackTrace();
					logger.error("关闭数据链接失败："+e.getMessage(),e);
				}
			}
		}
		
		//如果链接OK，则获取mybatis SQL session
		if(isConnectionOK){
			Map<String,String> properties = new HashMap<>();
			properties.put("url", bean.getUrl());
			properties.put("username", bean.getUsername());
			properties.put("password",bean.getPassword());
			String driverClassName = EDBType.getDriverClassNameByTypeCode(bean.getDb_type());
			properties.put("driverClassName", driverClassName);
			
			try {
				DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);
				
				SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
		        sqlSessionFactoryBean.setDataSource(dataSource);

		        PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
		        sqlSessionFactoryBean.setMapperLocations(resolver.getResources("classpath:mappers/*.xml"));
		        SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBean.getObject();
		        result =  sqlSessionFactory.openSession();
			} catch (Exception e) {
				e.printStackTrace();
				logger.error("数据库链接失败："+e.getMessage(),e);
				AlertUtil.showErrorAlert("数据库链接失败："+e.getMessage());
			}
		}
		return result;
	}
	
	/**
	 * 获取本子类支持的数据库类型
	 * @return
	 */
	public abstract EDBType getEDBType();
	
	/**
	 * 获取指定数据库的所有数据表信息
	 * @param dbName
	 * @return
	 */
	public abstract List<TableBaseInfoBean> getTableInfos(DBConnectInfoBean bean,String dbName);
	
	/**
	 * 获取指定库指定表格的所有数据表字段信息
	 * @param dbName
	 * @param tableName
	 * @return
	 */
	public abstract List<ColumnsBaseInfoBean> getColumnInfos(DBConnectInfoBean bean,String dbName,String tableName);
}
